package service

import (
	"context"
	"encoding/json"
	"time"

	"open/internal/model"
	"open/internal/model/event"
	"open/internal/model/field"
	"open/internal/types"

	"open/pkg/bytedance"
)

// CommitBytedanceMini 提交字节跳动小程序
func (s *Service) CommitBytedanceMini(ctx context.Context, appID string, biz json.RawMessage) error {
	// Step1: 设置服务器域名
	if err := s.dao.SetBytedanceDomains(ctx, appID); err != nil {
		return err
	}
	// Step2: 设置业务域名
	if err := s.dao.SetBytedanceWebViewDomains(ctx, appID); err != nil {
		return err
	}
	// Step3: 提交代码
	req := &bytedance.UploadPackageRequest{}
	if err := json.Unmarshal(biz, req); err != nil {
		return err
	}
	if err := s.dao.CommitBytedanceMini(ctx, appID, req); err != nil {
		return err
	}

	if err := s.dao.Transaction(ctx, func(ctx context.Context) error {
		appVersion, err := s.dao.GetAppVersion(ctx, appID, types.ByteDance)
		if err != nil {
			return err
		}
		jobData, _ := json.Marshal(req)
		// Step6: 新建提交审核任务
		schedule := &model.Schedule{
			RefID:     appVersion.ID,
			JobType:   types.TaskCommitAudit,
			JobData:   field.JSON("{}"),
			JobStatus: types.ScheduleTaskInit,
		}
		if err := s.dao.CreateSchedule(ctx, schedule); err != nil {
			return err
		}
		// Step: 发送事件
		if err := s.dao.TxSend(ctx, event.TaskCommitAudit{
			AppID:     appID,
			Platform:  types.ByteDance,
			JobID:     schedule.ID,
			Biz:       jobData,
			Timestamp: time.Now().Unix(),
		}); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return err
	}
	return nil
}

// CommitAuditBytedanceMini 提交字节跳动小程序审核
func (s *Service) CommitAuditBytedanceMini(ctx context.Context, appID string) error {
	if err := s.dao.CommitAuditBytedanceMini(ctx, appID); err != nil {
		if bdError, ok := err.(*bytedance.ErrorResponse); ok {
			switch bdError.ErrNo {
			case 10104, 10107, 10109, 11305, 11304, 11306:
				return s.innerRejectWithReason(ctx, appID, types.ByteDance, bdError.Message)
			case 11303:
				//已有版本在审核中，请审核后再提交
				return nil
			}
		}
		return err
	}
	if err := s.dao.Transaction(ctx, func(ctx context.Context) error {
		appVersion, err := s.dao.LockAppVersion(ctx, appID, types.ByteDance)
		if err != nil {
			return err
		}
		appVersion.Stage = types.StageAuditing
		if err = s.dao.SaveAppVersion(ctx, appVersion); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return err
	}
	return nil
}

// ReleaseBytedanceMini 发布字节跳动小程序
func (s *Service) ReleaseBytedanceMini(ctx context.Context, appID string) error {
	if err := s.dao.ReleaseBytedanceMini(ctx, appID); err != nil {
		return err
	}

	bytedanceMiniApp, err := s.dao.GetBytedanceMiniApp(ctx, appID)
	if err != nil {
		return err
	}
	if err := s.dao.Transaction(ctx, func(ctx context.Context) error {
		appVersion, err := s.dao.LockAppVersion(ctx, appID, types.Alipay)
		if err != nil {
			return err
		}
		appVersion.Stage = types.StageReleased
		appVersion.Status = types.StageReleased
		appVersion.AuditVersion = ""
		appVersion.ReleaseVersion = appVersion.AuditVersion
		if err = s.dao.SaveAppVersion(ctx, appVersion); err != nil {
			return err
		}
		if err = s.dao.CreateVersionLog(ctx, &model.MiniAppVersionLog{
			VersionID: appVersion.ID,
			Version:   appVersion.ReleaseVersion,
		}); err != nil {
			return err
		}
		if bytedanceMiniApp.QrCodeURL == "" {
			schedule := &model.Schedule{
				JobType:   types.TaskSyncQRCode,
				RefID:     appVersion.ID,
				JobData:   field.JSON("{}"),
				JobStatus: types.ScheduleTaskInit,
			}
			if err = s.dao.CreateSchedule(ctx, schedule); err != nil {
				return err
			}
			if err = s.dao.TxSend(ctx, event.TaskSyncQRCode{
				AppID:     appID,
				Platform:  types.ByteDance,
				Timestamp: time.Now().Unix(),
			}); err != nil {
				return err
			}
		}
		return nil
	}); err != nil {
		return err
	}
	return nil
}
